package com.zlc.common.util.context;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.zlc.common.annotation.DicItem;
import com.zlc.common.annotation.DicType;
import com.zlc.common.annotation.SyncDicConstant;
import com.zlc.common.common.service.ContextHolder;
import com.zlc.common.core.sys.model.vo.MayanPlatDicVo;
import com.zlc.common.core.sys.service.MayanPlatDicService;
import com.zlc.common.util.PlatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 字典信息初始化到数据库
 */
@Component
public class SysDicInit {

    @Autowired
    private MayanPlatDicService mayanPlatDicService;

    public void initDic(ApplicationContext context) {
        Map<String, Object> dicBeans = context.getBeansWithAnnotation(SyncDicConstant.class);
        ContextHolder.setDefaultUser();
        //查询所有系统参数
        List<MayanPlatDicVo> dbDic = mayanPlatDicService.queryVoList(new LambdaQueryWrapper<>());

        //需要保存的参数
        List<MayanPlatDicVo> saveList = new ArrayList<>();
        for (Object dicBean : dicBeans.values()) {
            initDicType(dicBean, saveList, dbDic);
            initDicItem(dicBean, saveList, dbDic);
        }
        if (!ObjectUtils.isEmpty(saveList)) {
            mayanPlatDicService.saveBatchVoList(saveList);
        }
    }


    private void initDicItem(Object dicBean, List<MayanPlatDicVo> saveList, List<MayanPlatDicVo> dbDic) {
        Field[] fields = dicBean.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            DicItem annotation = field.getAnnotation(DicItem.class);
            if (annotation != null) {
                String typeCode = annotation.typeCode();
                String value = annotation.value();
                String desc = annotation.desc();
                long order = annotation.order();
                //父级字典
                MayanPlatDicVo parentDic = dbDic.stream().filter(a -> a.getCode().equals(typeCode))
                        .findFirst().orElse(null);
                if (ObjectUtils.isEmpty(parentDic)) {
                    parentDic = saveList.stream().filter(save -> save.getCode().equals(typeCode)).findFirst().orElse(null);
                    if (ObjectUtils.isEmpty(parentDic)) {
                        //父级字典不存在跳过
                        continue;
                    }
                }
                //字典值
                MayanPlatDicVo dbItem = dbDic.stream().filter(dic -> dic.getCode().equals(value) && dic.getParentCode().equals(typeCode))
                        .findFirst().orElse(null);
                if (!ObjectUtils.isEmpty(dbItem)) {
                    //发生更新了,做修改
                    if (PlatUtils.hasChange(dbItem.getSystemFlag(), parentDic.getSystemFlag())
                            || PlatUtils.hasChange(dbItem.getValue(), desc)
                            || PlatUtils.hasChange(dbItem.getOrder(), order)) {
                        dbItem.setSystemFlag(parentDic.getSystemFlag());
                        dbItem.setRemark(desc);
                        dbItem.setValue(desc);
                        dbItem.setOrder(order);
                        saveList.add(dbItem);
                    }
                } else {
                    MayanPlatDicVo dicVo = new MayanPlatDicVo();
                    dicVo.setSystemFlag(parentDic.getSystemFlag());
                    dicVo.setParentCode(typeCode);
                    dicVo.setCode(value);
                    dicVo.setValue(desc);
                    dicVo.setRemark(desc);
                    dicVo.setStatus("ACTIVE");
                    dicVo.setOrder(order);
                    saveList.add(dicVo);
                }
            }
        }
    }

    private void initDicType(Object dicBean, List<MayanPlatDicVo> saveList, List<MayanPlatDicVo> dbDic) {
        Field[] fields = dicBean.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            DicType annotation = field.getAnnotation(DicType.class);
            if (annotation != null) {
                String typeCode = annotation.value();
                String desc = annotation.desc();
                boolean system = annotation.system();
                MayanPlatDicVo dicTypeVo = dbDic.stream().filter(a -> a.getCode().equals(typeCode))
                        .findFirst().orElse(null);
                if (!ObjectUtils.isEmpty(dicTypeVo)) {
                    //发生更新了,做修改
                    if (PlatUtils.hasChange(dicTypeVo.getValue(), desc) || PlatUtils.hasChange(dicTypeVo.getSystemFlag(), system)) {
                        dicTypeVo.setSystemFlag(system);
                        dicTypeVo.setRemark(desc);
                        dicTypeVo.setValue( desc);
                        saveList.add(dicTypeVo);
                    }
                } else {
                    MayanPlatDicVo dicVo = new MayanPlatDicVo();
                    dicVo.setSystemFlag(system);
                    dicVo.setCode(typeCode);
                    dicVo.setRemark(desc);
                    dicVo.setValue(desc);
                    dicVo.setStatus("ACTIVE");
                    saveList.add(dicVo);
                }
            }
        }
    }
}
